/**
 * PHOSIDE: PHosphorylation Site IDentification Engine.
 * Copyright 2009 Digital Biology Lab, University of Missouri.
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 3 of the License, or (at your option) any later
 * version. <p/> This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more
 * details.
 */

package phoside.ui;

import java.io.IOException;
import java.io.File;

import java.util.ArrayList;
import java.util.HashSet;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

import phoside.PhosideInit;
import phoside.Proteins;
import phoside.ProteinsImpl;

import phoside.data.feature.model.Instance;
import phoside.data.feature.model.InstanceUtil;
import phoside.data.feature.extaction.InstancesExtractor;
import phoside.data.feature.extaction.InstancesExtractorFromProteins;

import phoside.io.xml.PhosideXmlProteinsReader;
import phoside.io.xml.PhosphoProteinFieldValueFormatter;

import phoside.ui.task.ProteinsReadTask;
import phoside.ui.task.TaskUtil;

import phoside.util.FileExtensionsFilter;
import phoside.util.FilePathParser;
import phoside.util.IOUtil;

/**
 *
 * @author gjj
 */
public class SurroundSequenceExtractDialog extends javax.swing.JDialog {

    /** Creates new form Fasta2XmlDialog */
    public SurroundSequenceExtractDialog(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        initComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        javax.swing.JPanel fromPanel = new javax.swing.JPanel();
        javax.swing.JPanel fromFilePanel = new javax.swing.JPanel();
        fromFileTextField = new javax.swing.JTextField();
        javax.swing.JButton fromFileButton = new javax.swing.JButton();
        javax.swing.JPanel toPanel = new javax.swing.JPanel();
        javax.swing.JPanel toFilePanel = new javax.swing.JPanel();
        toFileTextField = new javax.swing.JTextField();
        javax.swing.JButton toFileButton = new javax.swing.JButton();
        javax.swing.JPanel OKPanel = new javax.swing.JPanel();
        OKBtn = new javax.swing.JButton();
        javax.swing.JButton cancelBtn = new javax.swing.JButton();
        optionPanel = new javax.swing.JPanel();
        javax.swing.JPanel offsetPanel = new javax.swing.JPanel();
        javax.swing.JLabel upLabel = new javax.swing.JLabel();
        upTextField = new javax.swing.JTextField();
        javax.swing.JLabel downLabel = new javax.swing.JLabel();
        downTextField = new javax.swing.JTextField();
        javax.swing.JPanel otheropPanel = new javax.swing.JPanel();
        markSitesCheckBox = new javax.swing.JCheckBox();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Surrounding sequence extraction");
        getContentPane().setLayout(new java.awt.GridBagLayout());

        fromPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("From PHOSIDE XML File"));
        fromPanel.setLayout(new java.awt.GridBagLayout());

        fromFilePanel.setLayout(new java.awt.GridBagLayout());

        fromFileTextField.setToolTipText("Please select a FASTA training file");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        fromFilePanel.add(fromFileTextField, gridBagConstraints);

        fromFileButton.setText("Open");
        fromFileButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                fromFileButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        fromFilePanel.add(fromFileButton, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        fromPanel.add(fromFilePanel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(fromPanel, gridBagConstraints);

        toPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Save to"));
        toPanel.setMinimumSize(new java.awt.Dimension(400, 63));
        toPanel.setPreferredSize(new java.awt.Dimension(500, 63));
        toPanel.setLayout(new java.awt.GridBagLayout());

        toFilePanel.setLayout(new java.awt.GridBagLayout());

        toFileTextField.setToolTipText("Please select a FASTA training file");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        toFilePanel.add(toFileTextField, gridBagConstraints);

        toFileButton.setText("Open");
        toFileButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                toFileButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        toFilePanel.add(toFileButton, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        toPanel.add(toFilePanel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(toPanel, gridBagConstraints);

        OKBtn.setText("   OK   ");
        OKBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                OKBtnActionPerformed(evt);
            }
        });
        OKPanel.add(OKBtn);

        cancelBtn.setText("Cancel");
        cancelBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cancelBtnActionPerformed(evt);
            }
        });
        OKPanel.add(cancelBtn);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(OKPanel, gridBagConstraints);

        optionPanel.setLayout(new java.awt.GridBagLayout());

        offsetPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Offset setting"));
        offsetPanel.setLayout(new java.awt.GridBagLayout());

        upLabel.setText("Upstream:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        offsetPanel.add(upLabel, gridBagConstraints);

        upTextField.setText("10");
        upTextField.setPreferredSize(new java.awt.Dimension(50, 19));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        offsetPanel.add(upTextField, gridBagConstraints);

        downLabel.setText("Downstream:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        offsetPanel.add(downLabel, gridBagConstraints);

        downTextField.setText("10");
        downTextField.setPreferredSize(new java.awt.Dimension(50, 19));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        offsetPanel.add(downTextField, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        optionPanel.add(offsetPanel, gridBagConstraints);

        otheropPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Other options"));

        markSitesCheckBox.setSelected(true);
        markSitesCheckBox.setText("Mark all phosphorylation sites");
        otheropPanel.add(markSitesCheckBox);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        optionPanel.add(otheropPanel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(optionPanel, gridBagConstraints);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void fromFileButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fromFileButtonActionPerformed
        JFileChooser fc = new JFileChooser(PhosideInit.defaultPath);
        ArrayList<String> exts = new ArrayList<String>(1);
        String ext = "xml";
        exts.add(ext);
        fc.setFileFilter(new FileExtensionsFilter(exts,"PHOSIDE XML file (.xml)"));
        //fc.setAcceptAllFileFilterUsed(true);
        fc.setDialogTitle("Select a PHOSIDE XML file...");
        int returnVal = fc.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            PhosideInit.defaultPath = file.getParent();

            String filePath = PhosideInit.defaultPath + File.separator + file.getName();
            fromFileTextField.setText(filePath);

            String fileName = FilePathParser.getName(filePath);
            toFileTextField.setText(PhosideInit.defaultPath+File.separator+fileName+"-seq.txt");
        }
}//GEN-LAST:event_fromFileButtonActionPerformed

    private void toFileButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_toFileButtonActionPerformed
        JFileChooser fc;
        String defFile = toFileTextField.getText();
        if (defFile.length()>0) {
            fc = new JFileChooser(FilePathParser.getDir(defFile));
        } else {
            fc = new JFileChooser(PhosideInit.defaultPath);
        }

        String ext = "txt";
        fc.setSelectedFile(new File(defFile));
        ArrayList<String> exts = new ArrayList<String>(1);
        exts.add(ext);
        fc.setFileFilter(new FileExtensionsFilter(exts,"Text file (.txt)"));
        //fc.setAcceptAllFileFilterUsed(true);
        fc.setDialogTitle("Save to...");
        int returnVal = fc.showSaveDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            PhosideInit.defaultPath = file.getParent();

            String filePath = PhosideInit.defaultPath + File.separator + file.getName();
            toFileTextField.setText(filePath);
        }
    }//GEN-LAST:event_toFileButtonActionPerformed

    private void OKBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_OKBtnActionPerformed
        String dirFrom = fromFileTextField.getText();
        if (dirFrom.length()==0) {
            JOptionPane.showMessageDialog(this, "Error: specify a file containing the protein sequences.");
            return;
        }

        String dirTo = toFileTextField.getText();
        if (dirTo.length()==0) {
            JOptionPane.showMessageDialog(this, "Error: specify the file to save.");
            return;
        }

        String up = this.upTextField.getText();
        if (up.length()==0) {
            JOptionPane.showMessageDialog(this, "Error: specify the upstream offset.");
            return;
        }

        int upOffset;
        try {
            upOffset = Integer.parseInt(up);
        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, "Error: specify the positive number as upstream offset.");
            return;
        }

        if (upOffset<=0) {
            JOptionPane.showMessageDialog(this, "Error: specify the positive number as upstream offset.");
            return;
        }

        String down = this.downTextField.getText();
        if (up.length()==0) {
            JOptionPane.showMessageDialog(this, "Error: specify the downstream offset.");
            return;
        }
        
        int downOffset;
        try {
            downOffset = Integer.parseInt(down);
        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, "Error: specify the positive number as downstream offset.");
            return;
        }
        
        if (downOffset<=0) {
            JOptionPane.showMessageDialog(this, "Error: specify the positive number as downstream offset.");
            return;
        }
        
        if (phoside.util.IOUtil.fileExist(dirTo)) {
            int ret = JOptionPane.showConfirmDialog(this, "Are you sure to replace the existing file?",
                    null, JOptionPane.YES_NO_OPTION);
            if (ret==JOptionPane.NO_OPTION) {
                return;
            }
        }

        //Reading xml data
        Proteins proteins = new ProteinsImpl();
        PhosideXmlProteinsReader phosphoReader = new PhosideXmlProteinsReader(
                dirFrom, proteins, new PhosphoProteinFieldValueFormatter());

        ProteinsReadTask phosphoReadTask = new ProteinsReadTask(phosphoReader);
        TaskUtil.execute(phosphoReadTask);
        if (!phosphoReadTask.success()) {
            JOptionPane.showMessageDialog(this, "Failed to read the xml file");
            return;
        }

        //
        java.util.Map<phoside.Protein, java.util.Set<String>> map
                = new java.util.LinkedHashMap();

        InstancesExtractor insExtractor = new InstancesExtractorFromProteins(proteins, null,
                new java.util.HashSet(java.util.Arrays.asList(phoside.PhosphoProteins.PhosphoType.values())),
                InstancesExtractor.PhosphoTag.PHOSPHO);
        java.util.List<Instance> instances = insExtractor.fetch(-1);
        for (Instance ins : instances) {
            Object obj = ins.getInstanceTag().getTag(phoside.util.StaticFinalValues.INSTANCETAGNAMEPROTEIN);
            if (obj==null || !(obj instanceof phoside.Protein)) {
                return;
            }
            phoside.Protein protein = (phoside.Protein)obj;

            String sequence = InstanceUtil.extractSurroundingSequence(ins, upOffset, downOffset,
                    true, markSitesCheckBox.isSelected());

            java.util.Set<String> seqs = map.get(protein);
            if (seqs==null) {
                seqs = new java.util.HashSet();
                map.put(protein, seqs);
            }

            seqs.add(sequence);
        }

        //Write to file
        try {
            java.io.FileWriter fout = new java.io.FileWriter(dirTo);
            java.io.BufferedWriter out = new java.io.BufferedWriter(fout);

            for (java.util.Map.Entry<phoside.Protein, java.util.Set<String>> entry : map.entrySet()) {
                phoside.Protein protein = entry.getKey();
                out.write(">"+protein.getAccession());
                out.newLine();
                for (String seq : entry.getValue()) {
                    out.write("\t"+seq);
                    out.newLine();
                }
            }

            out.close();
            fout.close();
        } catch(IOException e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, "Failed to write to the file.");
            return;
        }

        JOptionPane.showMessageDialog(this, "Successfully exported the accessions.");
        
        this.setVisible(false);
        this.dispose();
}//GEN-LAST:event_OKBtnActionPerformed

    private void cancelBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelBtnActionPerformed
        setVisible(false);
        dispose();
}//GEN-LAST:event_cancelBtnActionPerformed


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton OKBtn;
    private javax.swing.JTextField downTextField;
    private javax.swing.JTextField fromFileTextField;
    private javax.swing.JCheckBox markSitesCheckBox;
    private javax.swing.JPanel optionPanel;
    private javax.swing.JTextField toFileTextField;
    private javax.swing.JTextField upTextField;
    // End of variables declaration//GEN-END:variables

}
